/*      */ package com.zimbra.cs.account;
/*      */ 
/*      */ import com.google.common.annotations.VisibleForTesting;
/*      */ import com.zimbra.common.localconfig.KnownKey;
/*      */ import com.zimbra.common.localconfig.LC;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.SetUtil;
/*      */ import com.zimbra.common.util.Version;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.cs.account.callback.CallbackContext;
/*      */ import com.zimbra.cs.account.callback.IDNCallback;
/*      */ import com.zimbra.cs.account.ldap.LdapProv;
/*      */ import com.zimbra.cs.extension.ExtensionUtil;
/*      */ import java.io.File;
/*      */ import java.lang.reflect.Constructor;
/*      */ import java.util.ArrayList;
/*      */ import java.util.HashMap;
/*      */ import java.util.HashSet;
/*      */ import java.util.Iterator;
/*      */ import java.util.LinkedList;
/*      */ import java.util.List;
/*      */ import java.util.Map;
/*      */ import java.util.Set;
/*      */ import org.dom4j.Attribute;
/*      */ import org.dom4j.Document;
/*      */ import org.dom4j.DocumentException;
/*      */ import org.dom4j.Element;
/*      */ import org.dom4j.io.SAXReader;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public class AttributeManager
/*      */ {
/*      */   private static final String E_ATTRS = "attrs";
/*      */   private static final String E_OBJECTCLASSES = "objectclasses";
/*      */   private static final String A_GROUP = "group";
/*      */   private static final String A_GROUP_ID = "groupid";
/*      */   private static final String E_ATTR = "attr";
/*      */   private static final String A_NAME = "name";
/*      */   private static final String A_IMMUTABLE = "immutable";
/*      */   private static final String A_TYPE = "type";
/*      */   private static final String A_ORDER = "order";
/*      */   private static final String A_VALUE = "value";
/*      */   static final String A_MAX = "max";
/*      */   static final String A_MIN = "min";
/*      */   private static final String A_CALLBACK = "callback";
/*      */   private static final String A_ID = "id";
/*      */   private static final String A_PARENT_OID = "parentOid";
/*      */   private static final String A_CARDINALITY = "cardinality";
/*      */   private static final String A_REQUIRED_IN = "requiredIn";
/*      */   private static final String A_OPTIONAL_IN = "optionalIn";
/*      */   private static final String A_FLAGS = "flags";
/*      */   private static final String A_DEPRECATED_SINCE = "deprecatedSince";
/*      */   private static final String A_SINCE = "since";
/*      */   private static final String A_REQUIRES_RESTART = "requiresRestart";
/*      */   private static final String E_OBJECTCLASS = "objectclass";
/*      */   private static final String E_SUP = "sup";
/*      */   private static final String E_COMMENT = "comment";
/*      */   private static final String E_DESCRIPTION = "desc";
/*      */   private static final String E_DEPRECATE_DESC = "deprecateDesc";
/*      */   private static final String E_GLOBAL_CONFIG_VALUE = "globalConfigValue";
/*      */   private static final String E_GLOBAL_CONFIG_VALUE_UPGRADE = "globalConfigValueUpgrade";
/*      */   private static final String E_DEFAULT_COS_VALUE = "defaultCOSValue";
/*      */   private static final String E_DEFAULT_EXTERNAL_COS_VALUE = "defaultExternalCOSValue";
/*      */   private static final String E_DEFAULT_COS_VALUE_UPGRADE = "defaultCOSValueUpgrade";
/*      */   private static AttributeManager mInstance;
/*   95 */   private final Map<String, AttributeInfo> mAttrs = new HashMap();
/*      */   
/*   97 */   private final Map<String, ObjectClassInfo> mOCs = new HashMap();
/*      */   
/*      */ 
/*  100 */   private final Map<AttributeClass, Set<String>> mClassToAttrsMap = new HashMap();
/*  101 */   private final Map<AttributeClass, Set<String>> mClassToLowerCaseAttrsMap = new HashMap();
/*      */   
/*      */ 
/*  104 */   private final Map<AttributeClass, Set<String>> mClassToAllAttrsMap = new HashMap();
/*      */   
/*  106 */   private boolean mLdapSchemaExtensionInited = false;
/*      */   
/*  108 */   private final AttributeCallback mIDNCallback = new IDNCallback();
/*      */   
/*  110 */   private static Map<Integer, String> mGroupMap = new HashMap();
/*      */   
/*  112 */   private static Map<Integer, String> mOCGroupMap = new HashMap();
/*      */   
/*      */ 
/*  115 */   private static Set<String> mBinaryAttrs = new HashSet();
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*  120 */   private static Set<String> mBinaryTransferAttrs = new HashSet();
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  150 */   private static boolean mMinimize = false;
/*      */   
/*      */   public static AttributeManager getInst() {
/*      */     try {
/*  154 */       return getInstance();
/*      */     } catch (ServiceException e) {
/*  156 */       ZimbraLog.account.warn("could not get AttributeManager instance", e); }
/*  157 */     return null;
/*      */   }
/*      */   
/*      */   public static AttributeManager getInstance() throws ServiceException
/*      */   {
/*  162 */     synchronized (AttributeManager.class) {
/*  163 */       if (mInstance != null) {
/*  164 */         return mInstance;
/*      */       }
/*  166 */       String dir = LC.zimbra_attrs_directory.value();
/*  167 */       String className = LC.zimbra_class_attrmanager.value();
/*  168 */       if ((className != null) && (!className.equals(""))) {
/*      */         try {
/*      */           try {
/*  171 */             mInstance = (AttributeManager)Class.forName(className).getDeclaredConstructor(new Class[] { String.class }).newInstance(new Object[] { dir });
/*      */           }
/*      */           catch (ClassNotFoundException cnfe) {
/*  174 */             mInstance = (AttributeManager)ExtensionUtil.findClass(className).getDeclaredConstructor(new Class[] { String.class }).newInstance(new Object[] { dir });
/*      */           }
/*      */         } catch (Exception e) {
/*  177 */           ZimbraLog.account.debug("could not instantiate AttributeManager interface of class '" + className + "'; defaulting to AttributeManager");
/*      */         }
/*      */       }
/*  180 */       if (mInstance == null) {
/*  181 */         mInstance = new AttributeManager(dir);
/*      */       }
/*  183 */       if (mInstance.hasErrors()) {
/*  184 */         throw ServiceException.FAILURE(mInstance.getErrors(), null);
/*      */       }
/*      */       
/*  187 */       mInstance.computeClassToAllAttrsMap();
/*      */       
/*  189 */       return mInstance;
/*      */     }
/*      */   }
/*      */   
/*      */   public boolean isMultiValued(String attrName) {
/*  194 */     AttributeInfo attributeInfo = getAttributeInfo(attrName);
/*  195 */     return (attributeInfo != null) && (attributeInfo.getCardinality() == AttributeCardinality.multi);
/*      */   }
/*      */   
/*      */   @VisibleForTesting
/*      */   void addAttribute(AttributeInfo info) {
/*  200 */     this.mAttrs.put(info.mName.toLowerCase(), info);
/*      */   }
/*      */   
/*      */   @VisibleForTesting
/*      */   AttributeManager() {}
/*      */   
/*      */   public AttributeManager(String dir) throws ServiceException
/*      */   {
/*  208 */     initFlagsToAttrsMap();
/*  209 */     initClassToAttrsMap();
/*  210 */     File fdir = new File(dir);
/*  211 */     if (!fdir.exists()) {
/*  212 */       throw ServiceException.FAILURE("attrs directory does not exists: " + dir, null);
/*      */     }
/*  214 */     if (!fdir.isDirectory()) {
/*  215 */       throw ServiceException.FAILURE("attrs directory is not a directory: " + dir, null);
/*      */     }
/*      */     
/*  218 */     File[] files = fdir.listFiles();
/*  219 */     for (File file : files)
/*  220 */       if (!file.getPath().endsWith(".xml")) {
/*  221 */         ZimbraLog.misc.warn("while loading attrs, ignoring not .xml file: " + file);
/*      */       }
/*      */       else {
/*  224 */         if (!file.isFile()) {
/*  225 */           ZimbraLog.misc.warn("while loading attrs, ignored non-file: " + file);
/*      */         }
/*      */         try {
/*  228 */           SAXReader reader = new SAXReader();
/*  229 */           Document doc = reader.read(file);
/*  230 */           Element root = doc.getRootElement();
/*  231 */           if (root.getName().equals("attrs")) {
/*  232 */             loadAttrs(file);
/*  233 */           } else if (root.getName().equals("objectclasses")) {
/*  234 */             loadObjectClasses(file);
/*      */           } else {
/*  236 */             ZimbraLog.misc.warn("while loading attrs, ignored unknown file: " + file);
/*      */           }
/*      */         } catch (DocumentException de) {
/*  239 */           throw ServiceException.FAILURE("error loading attrs file: " + file, de);
/*      */         }
/*      */       }
/*      */   }
/*      */   
/*  244 */   private final List<String> mErrors = new LinkedList();
/*      */   
/*      */   boolean hasErrors() {
/*  247 */     return this.mErrors.size() > 0;
/*      */   }
/*      */   
/*      */   String getErrors() {
/*  251 */     StringBuilder result = new StringBuilder();
/*  252 */     for (String error : this.mErrors) {
/*  253 */       result.append(error).append("\n");
/*      */     }
/*  255 */     return result.toString();
/*      */   }
/*      */   
/*      */   Map<String, AttributeInfo> getAttrs()
/*      */   {
/*  260 */     return this.mAttrs;
/*      */   }
/*      */   
/*      */   Map<String, ObjectClassInfo> getOCs()
/*      */   {
/*  265 */     return this.mOCs;
/*      */   }
/*      */   
/*      */   Map<Integer, String> getGroupMap()
/*      */   {
/*  270 */     return mGroupMap;
/*      */   }
/*      */   
/*      */   Map<Integer, String> getOCGroupMap()
/*      */   {
/*  275 */     return mOCGroupMap;
/*      */   }
/*      */   
/*      */   private void error(String attrName, File file, String error) {
/*  279 */     if (attrName != null) {
/*  280 */       this.mErrors.add("attr " + attrName + " in file " + file + ": " + error);
/*      */     } else {
/*  282 */       this.mErrors.add("file " + file + ": " + error);
/*      */     }
/*      */   }
/*      */   
/*      */   private void loadAttrs(File file) throws DocumentException {
/*  287 */     SAXReader reader = new SAXReader();
/*  288 */     Document doc = reader.read(file);
/*  289 */     Element root = doc.getRootElement();
/*      */     
/*  291 */     if (!root.getName().equals("attrs")) {
/*  292 */       error(null, file, "root tag is not attrs");
/*  293 */       return;
/*      */     }
/*      */     
/*  296 */     Map<Integer, String> idsSeen = new HashMap();
/*      */     
/*  298 */     String group = root.attributeValue("group");
/*  299 */     String groupIdStr = root.attributeValue("groupid");
/*      */     
/*  301 */     if (((group == null ? 1 : 0) ^ (groupIdStr == null ? 1 : 0)) != 0) {
/*  302 */       error(null, file, "group and groupid both have to be both specified");
/*      */     }
/*  304 */     int groupId = -1;
/*  305 */     if (group != null) {
/*      */       try {
/*  307 */         groupId = Integer.valueOf(groupIdStr).intValue();
/*      */       } catch (NumberFormatException nfe) {
/*  309 */         error(null, file, "groupid is not a number: " + groupIdStr);
/*      */       }
/*      */     }
/*  312 */     if (groupId == 2) {
/*  313 */       error(null, file, "groupid is not valid (used by ZimbraObjectClass)");
/*  314 */     } else if (groupId > 0) {
/*  315 */       if (mGroupMap.containsKey(Integer.valueOf(groupId))) {
/*  316 */         error(null, file, "duplicate group id: " + groupId);
/*  317 */       } else if (mGroupMap.containsValue(group)) {
/*  318 */         error(null, file, "duplicate group: " + group);
/*      */       } else {
/*  320 */         mGroupMap.put(Integer.valueOf(groupId), group);
/*      */       }
/*      */     }
/*      */     
/*  324 */     for (Iterator iter = root.elementIterator(); iter.hasNext();) {
/*  325 */       Element eattr = (Element)iter.next();
/*  326 */       if (!eattr.getName().equals("attr")) {
/*  327 */         error(null, file, "unknown element: " + eattr.getName());
/*      */       }
/*      */       else
/*      */       {
/*  331 */         AttributeCallback callback = null;
/*  332 */         AttributeType type = null;
/*  333 */         AttributeOrder order = null;
/*  334 */         String value = null;
/*  335 */         String min = null;
/*  336 */         String max = null;
/*  337 */         boolean immutable = false;
/*      */         
/*  339 */         int id = -1;
/*  340 */         String parentOid = null;
/*  341 */         AttributeCardinality cardinality = null;
/*  342 */         Set<AttributeClass> requiredIn = null;
/*  343 */         Set<AttributeClass> optionalIn = null;
/*  344 */         Set<AttributeFlag> flags = null;
/*      */         
/*  346 */         String canonicalName = null;
/*  347 */         String name = eattr.attributeValue("name");
/*  348 */         if (name == null) {
/*  349 */           error(null, file, "no name specified");
/*      */         }
/*      */         else {
/*  352 */           canonicalName = name.toLowerCase();
/*      */           
/*  354 */           List<AttributeServerType> requiresRestart = null;
/*  355 */           Version deprecatedSinceVer = null;
/*  356 */           List<Version> sinceVer = null;
/*      */           
/*  358 */           Iterator attrIter = eattr.attributeIterator(); for (;;) { if (!attrIter.hasNext()) break label1384;
/*  359 */             Attribute attr = (Attribute)attrIter.next();
/*  360 */             String aname = attr.getName();
/*  361 */             if (!aname.equals("name"))
/*      */             {
/*  363 */               if (aname.equals("callback")) {
/*  364 */                 callback = loadCallback(attr.getValue());
/*  365 */               } else if (aname.equals("immutable")) {
/*  366 */                 immutable = "1".equals(attr.getValue());
/*  367 */               } else if (aname.equals("max")) {
/*  368 */                 max = attr.getValue();
/*  369 */               } else if (aname.equals("min")) {
/*  370 */                 min = attr.getValue();
/*  371 */               } else { if (aname.equals("type")) {
/*  372 */                   type = AttributeType.getType(attr.getValue());
/*  373 */                   if (type != null) break label1381;
/*  374 */                   error(name, file, "unknown <attr> type: " + attr.getValue());
/*  375 */                   break;
/*      */                 }
/*  377 */                 if (aname.equals("value")) {
/*  378 */                   value = attr.getValue();
/*  379 */                 } else if (aname.equals("parentOid")) {
/*  380 */                   parentOid = attr.getValue();
/*  381 */                   if (!parentOid.matches("^\\d+(\\.\\d+)+"))
/*  382 */                     error(name, file, "invalid parent OID " + parentOid + ": must be an OID");
/*  383 */                 } else if (aname.equals("id")) {
/*      */                   try {
/*  385 */                     id = Integer.parseInt(attr.getValue());
/*  386 */                     if (id < 0) {
/*  387 */                       error(name, file, "invalid id " + id + ": must be positive");
/*      */                     }
/*      */                   } catch (NumberFormatException nfe) {
/*  390 */                     error(name, file, aname + " is not a number: " + attr.getValue());
/*      */                   }
/*  392 */                 } else if (aname.equals("cardinality")) {
/*      */                   try {
/*  394 */                     cardinality = AttributeCardinality.valueOf(attr.getValue());
/*      */                   } catch (IllegalArgumentException iae) {
/*  396 */                     error(name, file, aname + " is not valid: " + attr.getValue());
/*      */                   }
/*  398 */                 } else if (aname.equals("requiredIn")) {
/*  399 */                   requiredIn = parseClasses(name, file, attr.getValue());
/*  400 */                 } else if (aname.equals("optionalIn")) {
/*  401 */                   optionalIn = parseClasses(name, file, attr.getValue());
/*  402 */                 } else if (aname.equals("flags")) {
/*  403 */                   flags = parseFlags(name, file, attr.getValue());
/*  404 */                 } else if (aname.equals("order")) {
/*      */                   try {
/*  406 */                     order = AttributeOrder.valueOf(attr.getValue());
/*      */                   } catch (IllegalArgumentException iae) {
/*  408 */                     error(name, file, aname + " is not valid: " + attr.getValue());
/*      */                   }
/*  410 */                 } else if (aname.equals("requiresRestart")) {
/*  411 */                   requiresRestart = parseRequiresRestart(name, file, attr.getValue());
/*      */                 }
/*  413 */                 else if (aname.equals("deprecatedSince")) {
/*  414 */                   String depreSince = attr.getValue();
/*  415 */                   if (depreSince != null) {
/*      */                     try {
/*  417 */                       deprecatedSinceVer = new Version(depreSince);
/*      */                     } catch (ServiceException e) {
/*  419 */                       error(name, file, aname + " is not valid: " + attr.getValue() + " (" + e.getMessage() + ")");
/*      */                     }
/*      */                   }
/*      */                 }
/*  423 */                 else if (aname.equals("since")) {
/*  424 */                   String since = attr.getValue();
/*  425 */                   if (since != null) {
/*      */                     try {
/*  427 */                       String[] versions = since.split(",");
/*  428 */                       sinceVer = new ArrayList();
/*  429 */                       for (String verStr : versions) {
/*  430 */                         sinceVer.add(new Version(verStr.trim()));
/*      */                       }
/*      */                     } catch (ServiceException e) {
/*  433 */                       error(name, file, aname + " is not valid: " + attr.getValue() + " (" + e.getMessage() + ")");
/*      */                     }
/*      */                   }
/*      */                 }
/*      */                 else {
/*  438 */                   error(name, file, "unknown <attr> attr: " + aname);
/*      */                 }
/*      */               } }
/*      */           }
/*  442 */           List<String> globalConfigValues = new LinkedList();
/*  443 */           List<String> globalConfigValuesUpgrade = null;
/*  444 */           List<String> defaultCOSValues = new LinkedList();
/*  445 */           List<String> defaultExternalCOSValues = new LinkedList();
/*  446 */           List<String> defaultCOSValuesUpgrade = null;
/*  447 */           String description = null;
/*  448 */           String deprecateDesc = null;
/*      */           
/*  450 */           for (Iterator elemIter = eattr.elementIterator(); elemIter.hasNext();) {
/*  451 */             Element elem = (Element)elemIter.next();
/*  452 */             if (elem.getName().equals("globalConfigValue")) {
/*  453 */               globalConfigValues.add(elem.getText());
/*  454 */             } else if (elem.getName().equals("globalConfigValueUpgrade")) {
/*  455 */               if (globalConfigValuesUpgrade == null)
/*  456 */                 globalConfigValuesUpgrade = new LinkedList();
/*  457 */               globalConfigValuesUpgrade.add(elem.getText());
/*  458 */             } else if (elem.getName().equals("defaultCOSValue")) {
/*  459 */               defaultCOSValues.add(elem.getText());
/*  460 */             } else if (elem.getName().equals("defaultExternalCOSValue")) {
/*  461 */               defaultExternalCOSValues.add(elem.getText());
/*  462 */             } else if (elem.getName().equals("defaultCOSValueUpgrade")) {
/*  463 */               if (defaultCOSValuesUpgrade == null)
/*  464 */                 defaultCOSValuesUpgrade = new LinkedList();
/*  465 */               defaultCOSValuesUpgrade.add(elem.getText());
/*  466 */             } else if (elem.getName().equals("desc")) {
/*  467 */               if (description != null) {
/*  468 */                 error(name, file, "more than one desc");
/*      */               }
/*  470 */               description = elem.getText();
/*  471 */             } else if (elem.getName().equals("deprecateDesc")) {
/*  472 */               if (deprecateDesc != null) {
/*  473 */                 error(name, file, "more than one deprecateDesc");
/*      */               }
/*  475 */               deprecateDesc = elem.getText();
/*      */             } else {
/*  477 */               error(name, file, "unknown element: " + elem.getName());
/*      */             }
/*      */           }
/*      */           
/*  481 */           if ((deprecatedSinceVer != null) && (deprecateDesc == null)) {
/*  482 */             error(name, file, "missing attr deprecatedSince");
/*  483 */           } else if ((deprecatedSinceVer == null) && (deprecateDesc != null)) {
/*  484 */             error(name, file, "missing element deprecateDesc");
/*      */           }
/*  486 */           if (deprecatedSinceVer != null) {
/*  487 */             String deprecateInfo = "Deprecated since: " + deprecatedSinceVer.toString() + ".  " + deprecateDesc;
/*  488 */             if (description == null) {
/*  489 */               description = deprecateInfo;
/*      */             } else {
/*  491 */               description = deprecateInfo + ".  Orig desc: " + description;
/*      */             }
/*      */           }
/*      */           
/*  495 */           if ((sinceVer == null) && (id >= 525)) {
/*  496 */             error(name, file, "missing since (required after(inclusive) oid 710)");
/*      */           }
/*      */           
/*      */ 
/*  500 */           if ((id > 0) && (cardinality == null)) {
/*  501 */             error(name, file, "cardinality not specified");
/*      */           }
/*      */           
/*      */ 
/*  505 */           if ((id > 0) && (optionalIn != null) && (optionalIn.isEmpty()) && (requiredIn != null) && (requiredIn.isEmpty())) {
/*  506 */             error(name, file, "atleast one of requiredIn or optionalIn must be specified");
/*      */           }
/*      */           
/*      */ 
/*  510 */           if (id > 0) {
/*  511 */             String idForAttr = (String)idsSeen.get(Integer.valueOf(id));
/*  512 */             if (idForAttr != null) {
/*  513 */               error(name, file, "duplicate id: " + id + " is already used for " + idForAttr);
/*      */             } else {
/*  515 */               idsSeen.put(Integer.valueOf(id), name);
/*      */             }
/*      */           }
/*      */           
/*      */ 
/*  520 */           checkFlag(name, file, flags, AttributeFlag.accountInherited, AttributeClass.account, AttributeClass.cos, null, requiredIn, optionalIn);
/*      */           
/*      */ 
/*  523 */           checkFlag(name, file, flags, AttributeFlag.accountCosDomainInherited, AttributeClass.account, AttributeClass.cos, AttributeClass.domain, requiredIn, optionalIn);
/*      */           
/*      */ 
/*  526 */           checkFlag(name, file, flags, AttributeFlag.domainInherited, AttributeClass.domain, AttributeClass.globalConfig, null, requiredIn, optionalIn);
/*      */           
/*      */ 
/*  529 */           checkFlag(name, file, flags, AttributeFlag.serverInherited, AttributeClass.server, AttributeClass.globalConfig, null, requiredIn, optionalIn);
/*      */           
/*      */ 
/*  532 */           checkFlag(name, file, flags, AttributeFlag.serverPreferAlwaysOn, AttributeClass.server, AttributeClass.alwaysOnCluster, null, requiredIn, optionalIn);
/*      */           
/*      */ 
/*      */ 
/*  536 */           if (cardinality == AttributeCardinality.single) {
/*  537 */             if (globalConfigValues.size() > 1) {
/*  538 */               error(name, file, "more than one global config value specified for cardinality " + AttributeCardinality.single);
/*      */             }
/*  540 */             if ((defaultCOSValues.size() > 1) || (defaultExternalCOSValues.size() > 1)) {
/*  541 */               error(name, file, "more than one default COS value specified for cardinality " + AttributeCardinality.single);
/*      */             }
/*      */           }
/*      */           
/*  545 */           AttributeInfo info = createAttributeInfo(name, id, parentOid, groupId, callback, type, order, value, immutable, min, max, cardinality, requiredIn, optionalIn, flags, globalConfigValues, defaultCOSValues, defaultExternalCOSValues, globalConfigValuesUpgrade, defaultCOSValuesUpgrade, mMinimize ? null : description, requiresRestart, sinceVer, deprecatedSinceVer);
/*      */           
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  551 */           if (this.mAttrs.get(canonicalName) != null) {
/*  552 */             error(name, file, "duplicate definiton");
/*      */           }
/*  554 */           this.mAttrs.put(canonicalName, info);
/*      */           
/*  556 */           if (flags != null) {
/*  557 */             for (AttributeFlag flag : flags) {
/*  558 */               ((Set)this.mFlagToAttrsMap.get(flag)).add(name);
/*  559 */               if (flag == AttributeFlag.accountCosDomainInherited) {
/*  560 */                 ((Set)this.mFlagToAttrsMap.get(AttributeFlag.accountInherited)).add(name);
/*      */               }
/*      */             }
/*      */           }
/*  564 */           if ((requiredIn != null) || (optionalIn != null)) {
/*  565 */             if (requiredIn != null) {
/*  566 */               for (AttributeClass klass : requiredIn) {
/*  567 */                 ((Set)this.mClassToAttrsMap.get(klass)).add(name);
/*  568 */                 ((Set)this.mClassToLowerCaseAttrsMap.get(klass)).add(name.toLowerCase());
/*      */               }
/*      */             }
/*  571 */             if (optionalIn != null) {
/*  572 */               for (AttributeClass klass : optionalIn) {
/*  573 */                 ((Set)this.mClassToAttrsMap.get(klass)).add(name);
/*  574 */                 ((Set)this.mClassToLowerCaseAttrsMap.get(klass)).add(name.toLowerCase());
/*      */               }
/*      */             }
/*      */           }
/*      */           
/*  579 */           if (isBinaryType(type)) {
/*  580 */             mBinaryAttrs.add(canonicalName);
/*  581 */           } else if (isBinaryTransferType(type))
/*  582 */             mBinaryTransferAttrs.add(canonicalName);
/*      */         } } }
/*      */     label1381:
/*      */     label1384:
/*  586 */     return;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   protected AttributeInfo createAttributeInfo(String name, int id, String parentOid, int groupId, AttributeCallback callback, AttributeType type, AttributeOrder order, String value, boolean immutable, String min, String max, AttributeCardinality cardinality, Set<AttributeClass> requiredIn, Set<AttributeClass> optionalIn, Set<AttributeFlag> flags, List<String> globalConfigValues, List<String> defaultCOSValues, List<String> defaultExternalCOSValues, List<String> globalConfigValuesUpgrade, List<String> defaultCOSValuesUpgrade, String description, List<AttributeServerType> requiresRestart, List<Version> sinceVer, Version deprecatedSinceVer)
/*      */   {
/*  598 */     return new AttributeInfo(name, id, parentOid, groupId, callback, type, order, value, immutable, min, max, cardinality, requiredIn, optionalIn, flags, globalConfigValues, defaultCOSValues, defaultExternalCOSValues, globalConfigValuesUpgrade, defaultCOSValuesUpgrade, description, requiresRestart, sinceVer, deprecatedSinceVer);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   private static enum ObjectClassType
/*      */   {
/*  606 */     ABSTRACT, 
/*  607 */     AUXILIARY, 
/*  608 */     STRUCTURAL;
/*      */     
/*      */     private ObjectClassType() {}
/*      */   }
/*      */   
/*      */   class ObjectClassInfo
/*      */   {
/*      */     private final AttributeClass mAttributeClass;
/*      */     private final String mName;
/*      */     private final int mId;
/*      */     private final int mGroupId;
/*      */     private final AttributeManager.ObjectClassType mType;
/*      */     private final List<String> mSuperOCs;
/*      */     private final String mDescription;
/*      */     private final List<String> mComment;
/*      */     
/*      */     ObjectClassInfo(String attrClass, int ocName, int id, AttributeManager.ObjectClassType groupId, List<String> type, String superOCs, List<String> description)
/*      */     {
/*  626 */       this.mAttributeClass = attrClass;
/*  627 */       this.mName = ocName;
/*  628 */       this.mId = id;
/*  629 */       this.mGroupId = groupId;
/*  630 */       this.mType = type;
/*  631 */       this.mSuperOCs = superOCs;
/*  632 */       this.mDescription = description;
/*  633 */       this.mComment = comment;
/*      */     }
/*      */     
/*      */     AttributeClass getAttributeClass() {
/*  637 */       return this.mAttributeClass;
/*      */     }
/*      */     
/*      */     String getName() {
/*  641 */       return this.mName;
/*      */     }
/*      */     
/*      */     int getId() {
/*  645 */       return this.mId;
/*      */     }
/*      */     
/*      */     int getGroupId() {
/*  649 */       return this.mGroupId;
/*      */     }
/*      */     
/*      */     AttributeManager.ObjectClassType getType() {
/*  653 */       return this.mType;
/*      */     }
/*      */     
/*      */     List<String> getSuperOCs() {
/*  657 */       return this.mSuperOCs;
/*      */     }
/*      */     
/*      */     String getDescription() {
/*  661 */       return this.mDescription;
/*      */     }
/*      */     
/*      */     List<String> getComment() {
/*  665 */       return this.mComment;
/*      */     }
/*      */   }
/*      */   
/*      */   private void loadObjectClasses(File file) throws DocumentException
/*      */   {
/*  671 */     SAXReader reader = new SAXReader();
/*  672 */     Document doc = reader.read(file);
/*  673 */     Element root = doc.getRootElement();
/*      */     
/*  675 */     if (!root.getName().equals("objectclasses")) {
/*  676 */       error(null, file, "root tag is not objectclasses");
/*  677 */       return;
/*      */     }
/*      */     
/*  680 */     String group = root.attributeValue("group");
/*  681 */     String groupIdStr = root.attributeValue("groupid");
/*  682 */     if (((group == null ? 1 : 0) ^ (groupIdStr == null ? 1 : 0)) != 0) {
/*  683 */       error(null, file, "group and groupid both have to be both specified");
/*      */     }
/*  685 */     int groupId = -1;
/*  686 */     if (group != null) {
/*      */       try {
/*  688 */         groupId = Integer.valueOf(groupIdStr).intValue();
/*      */       } catch (NumberFormatException nfe) {
/*  690 */         error(null, file, "groupid is not a number: " + groupIdStr);
/*      */       }
/*      */     }
/*  693 */     if (groupId == 1) {
/*  694 */       error(null, file, "groupid is not valid (used by ZimbraAttrType)");
/*  695 */     } else if (groupId > 0) {
/*  696 */       if (mOCGroupMap.containsKey(Integer.valueOf(groupId))) {
/*  697 */         error(null, file, "duplicate group id: " + groupId);
/*  698 */       } else if (mOCGroupMap.containsValue(group)) {
/*  699 */         error(null, file, "duplicate group: " + group);
/*      */       } else {
/*  701 */         mOCGroupMap.put(Integer.valueOf(groupId), group);
/*      */       }
/*      */     }
/*      */     
/*  705 */     for (Iterator iter = root.elementIterator(); iter.hasNext();) {
/*  706 */       Element eattr = (Element)iter.next();
/*  707 */       if (!eattr.getName().equals("objectclass")) {
/*  708 */         error(null, file, "unknown element: " + eattr.getName());
/*      */       }
/*      */       else
/*      */       {
/*  712 */         int id = -1;
/*  713 */         ObjectClassType type = null;
/*  714 */         String canonicalName = null;
/*  715 */         String name = eattr.attributeValue("name");
/*  716 */         if (name == null) {
/*  717 */           error(null, file, "no name specified");
/*      */         }
/*      */         else {
/*  720 */           canonicalName = name.toLowerCase();
/*      */           
/*  722 */           for (Iterator attrIter = eattr.attributeIterator(); attrIter.hasNext();) {
/*  723 */             Attribute attr = (Attribute)attrIter.next();
/*  724 */             String aname = attr.getName();
/*  725 */             if (!aname.equals("name"))
/*      */             {
/*  727 */               if (aname.equals("type")) {
/*  728 */                 type = ObjectClassType.valueOf(attr.getValue());
/*  729 */               } else if (aname.equals("id")) {
/*      */                 try {
/*  731 */                   id = Integer.parseInt(attr.getValue());
/*  732 */                   if (id < 0) {
/*  733 */                     error(name, file, "invalid id " + id + ": must be positive");
/*      */                   }
/*      */                 } catch (NumberFormatException nfe) {
/*  736 */                   error(name, file, aname + " is not a number: " + attr.getValue());
/*      */                 }
/*      */               } else {
/*  739 */                 error(name, file, "unknown <attr> attr: " + aname);
/*      */               }
/*      */             }
/*      */           }
/*  743 */           List<String> superOCs = new LinkedList();
/*  744 */           String description = null;
/*  745 */           List<String> comment = null;
/*  746 */           for (Iterator elemIter = eattr.elementIterator(); elemIter.hasNext();) {
/*  747 */             Element elem = (Element)elemIter.next();
/*  748 */             if (elem.getName().equals("sup")) {
/*  749 */               superOCs.add(elem.getText());
/*  750 */             } else if (elem.getName().equals("desc")) {
/*  751 */               if (description != null) {
/*  752 */                 error(name, file, "more than one desc");
/*      */               }
/*  754 */               description = elem.getText();
/*  755 */             } else if (elem.getName().equals("comment")) {
/*  756 */               if (comment != null) {
/*  757 */                 error(name, file, "more than one comment");
/*      */               }
/*  759 */               comment = new ArrayList();
/*  760 */               String[] lines = elem.getText().trim().split("\\n");
/*  761 */               for (String line : lines)
/*  762 */                 comment.add(line.trim());
/*      */             } else {
/*  764 */               error(name, file, "unknown element: " + elem.getName());
/*      */             }
/*      */           }
/*      */           
/*      */ 
/*  769 */           if (id <= 0) {
/*  770 */             error(name, file, "id not specified");
/*      */           }
/*      */           
/*  773 */           if (type == null) {
/*  774 */             error(name, file, "type not specified");
/*      */           }
/*      */           
/*  777 */           if (description == null) {
/*  778 */             error(name, file, "desc not specified");
/*      */           }
/*      */           
/*  781 */           if (superOCs.isEmpty()) {
/*  782 */             error(name, file, "sup not specified");
/*      */           }
/*      */           
/*      */ 
/*  786 */           AttributeClass attrClass = AttributeClass.getAttributeClass(name);
/*  787 */           if (attrClass == null) {
/*  788 */             error(name, file, "unknown class in AttributeClass: " + name);
/*      */           }
/*      */           
/*  791 */           ObjectClassInfo info = new ObjectClassInfo(attrClass, name, id, groupId, type, superOCs, mMinimize ? null : description, mMinimize ? null : comment);
/*      */           
/*  793 */           if (this.mOCs.get(canonicalName) != null) {
/*  794 */             error(name, file, "duplicate objectclass definiton");
/*      */           }
/*  796 */           this.mOCs.put(canonicalName, info);
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   private Set<AttributeClass> parseClasses(String attrName, File file, String value) {
/*  803 */     Set<AttributeClass> result = new HashSet();
/*  804 */     String[] cnames = value.split(",");
/*  805 */     for (String cname : cnames) {
/*      */       try {
/*  807 */         AttributeClass ac = AttributeClass.valueOf(cname);
/*  808 */         if (result.contains(ac)) {
/*  809 */           error(attrName, file, "duplicate class: " + cname);
/*      */         }
/*  811 */         result.add(ac);
/*      */       } catch (IllegalArgumentException iae) {
/*  813 */         error(attrName, file, "invalid class: " + cname);
/*      */       }
/*      */     }
/*  816 */     return result;
/*      */   }
/*      */   
/*      */   private Set<AttributeFlag> parseFlags(String attrName, File file, String value) {
/*  820 */     Set<AttributeFlag> result = new HashSet();
/*  821 */     String[] flags = value.split(",");
/*  822 */     for (String flag : flags) {
/*      */       try {
/*  824 */         AttributeFlag ac = AttributeFlag.valueOf(flag);
/*  825 */         if (result.contains(ac)) {
/*  826 */           error(attrName, file, "duplicate flag: " + flag);
/*      */         }
/*  828 */         result.add(ac);
/*      */       } catch (IllegalArgumentException iae) {
/*  830 */         error(attrName, file, "invalid flag: " + flag);
/*      */       }
/*      */     }
/*  833 */     return result;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private void checkFlag(String attrName, File file, Set<AttributeFlag> flags, AttributeFlag flag, AttributeClass c1, AttributeClass c2, AttributeClass c3, Set<AttributeClass> required, Set<AttributeClass> optional)
/*      */   {
/*  840 */     if ((flags != null) && (flags.contains(flag))) {
/*  841 */       boolean inC1 = ((optional != null) && (optional.contains(c1))) || ((required != null) && (required.contains(c1)));
/*  842 */       boolean inC2 = ((optional != null) && (optional.contains(c2))) || ((required != null) && (required.contains(c2)));
/*  843 */       boolean inC3 = c3 == null;
/*  844 */       if ((!inC1) || (!inC2) || (!inC3)) {
/*  845 */         String classes = c1 + " and " + c2 + (c3 == null ? "" : new StringBuilder().append(" and ").append(c3).toString());
/*  846 */         error(attrName, file, "flag " + flag + " requires that attr be in all these classes: " + classes);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   private List<AttributeServerType> parseRequiresRestart(String attrName, File file, String value) {
/*  852 */     List<AttributeServerType> result = new ArrayList();
/*  853 */     String[] serverTypes = value.split(",");
/*  854 */     for (String server : serverTypes) {
/*      */       try {
/*  856 */         AttributeServerType ast = AttributeServerType.valueOf(server);
/*  857 */         if (result.contains(ast)) {
/*  858 */           error(attrName, file, "duplicate server type: " + server);
/*      */         }
/*  860 */         result.add(ast);
/*      */       } catch (IllegalArgumentException iae) {
/*  862 */         error(attrName, file, "invalid server type: " + server);
/*      */       }
/*      */     }
/*  865 */     return result;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   private void initClassToAttrsMap()
/*      */   {
/*  873 */     for (AttributeClass klass : ) {
/*  874 */       this.mClassToAttrsMap.put(klass, new HashSet());
/*  875 */       this.mClassToLowerCaseAttrsMap.put(klass, new HashSet());
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private void computeClassToAllAttrsMap()
/*      */   {
/*  883 */     for (AttributeClass klass : this.mClassToAttrsMap.keySet()) {
/*      */       Set<String> attrs;
/*  885 */       switch (klass) {
/*      */       case account: 
/*  887 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.mailRecipient), (Set)this.mClassToAttrsMap.get(AttributeClass.account));
/*      */         
/*      */ 
/*  890 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  891 */         break;
/*      */       case calendarResource: 
/*  893 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.mailRecipient), (Set)this.mClassToAttrsMap.get(AttributeClass.account));
/*      */         
/*      */ 
/*  896 */         attrs = SetUtil.union(attrs, (Set)this.mClassToAttrsMap.get(AttributeClass.calendarResource));
/*      */         
/*  898 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  899 */         break;
/*      */       case distributionList: 
/*  901 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.mailRecipient), (Set)this.mClassToAttrsMap.get(AttributeClass.distributionList));
/*      */         
/*      */ 
/*  904 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  905 */         break;
/*      */       case imapDataSource: 
/*  907 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.dataSource), (Set)this.mClassToAttrsMap.get(AttributeClass.imapDataSource));
/*      */         
/*      */ 
/*  910 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  911 */         break;
/*      */       case pop3DataSource: 
/*  913 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.dataSource), (Set)this.mClassToAttrsMap.get(AttributeClass.pop3DataSource));
/*      */         
/*      */ 
/*  916 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  917 */         break;
/*      */       case rssDataSource: 
/*  919 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.dataSource), (Set)this.mClassToAttrsMap.get(AttributeClass.rssDataSource));
/*      */         
/*      */ 
/*  922 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  923 */         break;
/*      */       case liveDataSource: 
/*  925 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.dataSource), (Set)this.mClassToAttrsMap.get(AttributeClass.liveDataSource));
/*      */         
/*      */ 
/*  928 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  929 */         break;
/*      */       case galDataSource: 
/*  931 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.dataSource), (Set)this.mClassToAttrsMap.get(AttributeClass.galDataSource));
/*      */         
/*      */ 
/*  934 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  935 */         break;
/*      */       case domain: 
/*  937 */         attrs = SetUtil.union(new HashSet(), (Set)this.mClassToAttrsMap.get(AttributeClass.mailRecipient), (Set)this.mClassToAttrsMap.get(AttributeClass.domain));
/*      */         
/*      */ 
/*  940 */         this.mClassToAllAttrsMap.put(klass, attrs);
/*  941 */         break;
/*      */       default: 
/*  943 */         this.mClassToAllAttrsMap.put(klass, this.mClassToAttrsMap.get(klass));
/*      */       }
/*      */       
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*  952 */   private final Map<AttributeFlag, Set<String>> mFlagToAttrsMap = new HashMap();
/*      */   
/*      */   private void initFlagsToAttrsMap() {
/*  955 */     for (AttributeFlag flag : ) {
/*  956 */       this.mFlagToAttrsMap.put(flag, new HashSet());
/*      */     }
/*      */   }
/*      */   
/*      */   public boolean isAccountInherited(String attr) {
/*  961 */     return ((Set)this.mFlagToAttrsMap.get(AttributeFlag.accountInherited)).contains(attr);
/*      */   }
/*      */   
/*      */   public boolean isAccountCosDomainInherited(String attr) {
/*  965 */     return ((Set)this.mFlagToAttrsMap.get(AttributeFlag.accountCosDomainInherited)).contains(attr);
/*      */   }
/*      */   
/*      */   public boolean isDomainInherited(String attr) {
/*  969 */     return ((Set)this.mFlagToAttrsMap.get(AttributeFlag.domainInherited)).contains(attr);
/*      */   }
/*      */   
/*      */   public boolean isServerInherited(String attr) {
/*  973 */     return ((Set)this.mFlagToAttrsMap.get(AttributeFlag.serverInherited)).contains(attr);
/*      */   }
/*      */   
/*      */   public boolean isDomainAdminModifiable(String attr, AttributeClass klass) throws ServiceException
/*      */   {
/*  978 */     if (!((Set)this.mClassToAllAttrsMap.get(klass)).contains(attr)) {
/*  979 */       throw AccountServiceException.INVALID_ATTR_NAME("unknown attribute on " + klass.name() + ": " + attr, null);
/*      */     }
/*  981 */     return ((Set)this.mFlagToAttrsMap.get(AttributeFlag.domainAdminModifiable)).contains(attr);
/*      */   }
/*      */   
/*      */   public void makeDomainAdminModifiable(String attr) {
/*  985 */     ((Set)this.mFlagToAttrsMap.get(AttributeFlag.domainAdminModifiable)).add(attr);
/*      */   }
/*      */   
/*      */   public static enum IDNType {
/*  989 */     email, 
/*  990 */     emailp, 
/*  991 */     cs_emailp, 
/*  992 */     idn, 
/*  993 */     none;
/*      */     
/*      */     private IDNType() {}
/*  996 */     public boolean isEmailOrIDN() { return this != none; }
/*      */   }
/*      */   
/*      */   public static IDNType idnType(AttributeManager am, String attr)
/*      */   {
/* 1001 */     if (am == null) {
/* 1002 */       return IDNType.none;
/*      */     }
/* 1004 */     return am.idnType(attr);
/*      */   }
/*      */   
/*      */   private IDNType idnType(String attr) {
/* 1008 */     AttributeInfo ai = (AttributeInfo)this.mAttrs.get(attr.toLowerCase());
/* 1009 */     if (ai != null) {
/* 1010 */       AttributeType at = ai.getType();
/* 1011 */       if (at == AttributeType.TYPE_EMAIL)
/* 1012 */         return IDNType.email;
/* 1013 */       if (at == AttributeType.TYPE_EMAILP)
/* 1014 */         return IDNType.emailp;
/* 1015 */       if (at == AttributeType.TYPE_CS_EMAILP)
/* 1016 */         return IDNType.cs_emailp;
/* 1017 */       if (((Set)this.mFlagToAttrsMap.get(AttributeFlag.idn)).contains(attr)) {
/* 1018 */         return IDNType.idn;
/*      */       }
/*      */     }
/* 1021 */     return IDNType.none;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean inVersion(String attr, String version)
/*      */     throws ServiceException
/*      */   {
/* 1041 */     return versionCheck(attr, version, true, true);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public boolean beforeVersion(String attr, String version)
/*      */     throws ServiceException
/*      */   {
/* 1058 */     return versionCheck(attr, version, false, true);
/*      */   }
/*      */   
/*      */   private boolean versionCheck(String attr, String version, boolean in, boolean before) throws ServiceException {
/* 1062 */     AttributeInfo ai = (AttributeInfo)this.mAttrs.get(attr.toLowerCase());
/* 1063 */     if (ai != null) {
/* 1064 */       List<Version> since = ai.getSince();
/* 1065 */       if (since == null) {
/* 1066 */         return true;
/*      */       }
/* 1068 */       Version current = new Version(version);
/* 1069 */       boolean good = false;
/* 1070 */       for (Version sinceVer : since) {
/* 1071 */         if (current.isSameMinorRelease(sinceVer))
/*      */         {
/* 1073 */           return ((before) && (sinceVer.compare(version) < 0)) || ((in) && (sinceVer.compare(version) == 0)); }
/* 1074 */         if (!current.isLaterMajorMinorRelease(sinceVer))
/*      */         {
/*      */ 
/* 1077 */           return good;
/*      */         }
/*      */         
/* 1080 */         good = ((before) && (sinceVer.compare(version) < 0)) || ((in) && (sinceVer.compare(version) == 0));
/*      */       }
/*      */       
/* 1083 */       return good;
/*      */     }
/*      */     
/* 1086 */     throw AccountServiceException.INVALID_ATTR_NAME("unknown attribute: " + attr, null);
/*      */   }
/*      */   
/*      */   public boolean isFuture(String attr)
/*      */   {
/* 1091 */     AttributeInfo ai = (AttributeInfo)this.mAttrs.get(attr.toLowerCase());
/* 1092 */     return (ai != null) && (ai.getSince() != null) && (ai.getSince().size() == 1) && (((Version)ai.getSince().iterator().next()).isFuture());
/*      */   }
/*      */   
/*      */   public boolean addedIn(String attr, String version) throws ServiceException {
/* 1096 */     return versionCheck(attr, version, true, false);
/*      */   }
/*      */   
/*      */   public AttributeType getAttributeType(String attr)
/*      */     throws ServiceException
/*      */   {
/* 1102 */     AttributeInfo ai = (AttributeInfo)this.mAttrs.get(attr.toLowerCase());
/* 1103 */     if (ai != null) {
/* 1104 */       return ai.getType();
/*      */     }
/* 1106 */     throw AccountServiceException.INVALID_ATTR_NAME("unknown attribute: " + attr, null);
/*      */   }
/*      */   
/*      */ 
/*      */   public static boolean isBinaryType(AttributeType type)
/*      */   {
/* 1112 */     return type == AttributeType.TYPE_BINARY;
/*      */   }
/*      */   
/*      */ 
/*      */   public static boolean isBinaryTransferType(AttributeType type)
/*      */   {
/* 1118 */     return type == AttributeType.TYPE_CERTIFICATE;
/*      */   }
/*      */   
/*      */   public boolean containsBinaryData(String attr) {
/* 1122 */     return (mBinaryAttrs.contains(attr.toLowerCase())) || (mBinaryTransferAttrs.contains(attr.toLowerCase()));
/*      */   }
/*      */   
/*      */   public boolean isBinaryTransfer(String attr)
/*      */   {
/* 1127 */     return mBinaryTransferAttrs.contains(attr.toLowerCase());
/*      */   }
/*      */   
/*      */   public Set<String> getBinaryAttrs() {
/* 1131 */     return mBinaryAttrs;
/*      */   }
/*      */   
/*      */   public Set<String> getBinaryTransferAttrs() {
/* 1135 */     return mBinaryTransferAttrs;
/*      */   }
/*      */   
/*      */   boolean hasFlag(AttributeFlag flag, String attr) {
/* 1139 */     return ((Set)this.mFlagToAttrsMap.get(flag)).contains(attr);
/*      */   }
/*      */   
/*      */   public Set<String> getAttrsWithFlag(AttributeFlag flag) {
/* 1143 */     return (Set)this.mFlagToAttrsMap.get(flag);
/*      */   }
/*      */   
/*      */   public Set<String> getAttrsInClass(AttributeClass klass) {
/* 1147 */     return (Set)this.mClassToAttrsMap.get(klass);
/*      */   }
/*      */   
/*      */   public Set<String> getAllAttrsInClass(AttributeClass klass) {
/* 1151 */     return (Set)this.mClassToAllAttrsMap.get(klass);
/*      */   }
/*      */   
/*      */   public Set<String> getLowerCaseAttrsInClass(AttributeClass klass) {
/* 1155 */     return (Set)this.mClassToLowerCaseAttrsMap.get(klass);
/*      */   }
/*      */   
/*      */   public Set<String> getImmutableAttrs() {
/* 1159 */     Set<String> immutable = new HashSet();
/* 1160 */     for (AttributeInfo info : this.mAttrs.values()) {
/* 1161 */       if ((info != null) && (info.isImmutable()))
/* 1162 */         immutable.add(info.getName());
/*      */     }
/* 1164 */     return immutable;
/*      */   }
/*      */   
/*      */   public Set<String> getImmutableAttrsInClass(AttributeClass klass) {
/* 1168 */     Set<String> immutable = new HashSet();
/* 1169 */     for (String attr : (Set)this.mClassToAttrsMap.get(klass)) {
/* 1170 */       AttributeInfo info = (AttributeInfo)this.mAttrs.get(attr.toLowerCase());
/* 1171 */       if (info != null) {
/* 1172 */         if (info.isImmutable())
/* 1173 */           immutable.add(attr);
/*      */       } else {
/* 1175 */         ZimbraLog.misc.warn("getImmutableAttrsInClass: no attribute info for: " + attr);
/*      */       }
/*      */     }
/* 1178 */     return immutable;
/*      */   }
/*      */   
/* 1181 */   public static void setMinimize(boolean minimize) { mMinimize = minimize; }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   private static AttributeCallback loadCallback(String clazz)
/*      */   {
/* 1188 */     AttributeCallback cb = null;
/* 1189 */     if (clazz == null)
/* 1190 */       return null;
/* 1191 */     if (clazz.indexOf('.') == -1)
/* 1192 */       clazz = "com.zimbra.cs.account.callback." + clazz;
/*      */     try {
/* 1194 */       cb = (AttributeCallback)Class.forName(clazz).newInstance();
/*      */     } catch (Exception e) {
/* 1196 */       ZimbraLog.misc.warn("loadCallback caught exception", e);
/*      */     }
/* 1198 */     return cb;
/*      */   }
/*      */   
/*      */   public void preModify(Map<String, ? extends Object> attrs, Entry entry, CallbackContext context, boolean checkImmutable)
/*      */     throws ServiceException
/*      */   {
/* 1204 */     preModify(attrs, entry, context, checkImmutable, true);
/*      */   }
/*      */   
/*      */   public void preModify(Map<String, ? extends Object> attrs, Entry entry, CallbackContext context, boolean checkImmutable, boolean allowCallback)
/*      */     throws ServiceException
/*      */   {
/* 1210 */     String[] keys = (String[])attrs.keySet().toArray(new String[0]);
/* 1211 */     for (int i = 0; i < keys.length; i++) {
/* 1212 */       String name = keys[i];
/* 1213 */       if (name.length() == 0) {
/* 1214 */         throw AccountServiceException.INVALID_ATTR_NAME("empty attr name found", null);
/*      */       }
/* 1216 */       Object value = attrs.get(name);
/* 1217 */       if ((name.charAt(0) == '-') || (name.charAt(0) == '+')) name = name.substring(1);
/* 1218 */       AttributeInfo info = (AttributeInfo)this.mAttrs.get(name.toLowerCase());
/* 1219 */       if (info != null) {
/* 1220 */         if (info.isDeprecated()) {
/* 1221 */           ZimbraLog.misc.warn("Attempt to modify a deprecated attribute: " + name);
/*      */         }
/*      */         
/*      */ 
/*      */ 
/* 1226 */         if (idnType(name).isEmailOrIDN()) {
/* 1227 */           this.mIDNCallback.preModify(context, name, value, attrs, entry);
/* 1228 */           value = attrs.get(name);
/*      */         }
/* 1230 */         info.checkValue(value, checkImmutable, attrs);
/* 1231 */         if ((allowCallback) && (info.getCallback() != null)) {
/* 1232 */           info.getCallback().preModify(context, name, value, attrs, entry);
/*      */         }
/*      */       } else {
/* 1235 */         ZimbraLog.misc.warn("checkValue: no attribute info for: " + name);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   public void postModify(Map<String, ? extends Object> attrs, Entry entry, CallbackContext context)
/*      */   {
/* 1242 */     postModify(attrs, entry, context, true);
/*      */   }
/*      */   
/*      */   public void postModify(Map<String, ? extends Object> attrs, Entry entry, CallbackContext context, boolean allowCallback)
/*      */   {
/* 1247 */     String[] keys = (String[])attrs.keySet().toArray(new String[0]);
/* 1248 */     for (int i = 0; i < keys.length; i++) {
/* 1249 */       String name = keys[i];
/*      */       
/* 1251 */       if ((name.charAt(0) == '-') || (name.charAt(0) == '+')) name = name.substring(1);
/* 1252 */       AttributeInfo info = (AttributeInfo)this.mAttrs.get(name.toLowerCase());
/* 1253 */       if ((info != null) && 
/* 1254 */         (allowCallback) && (info.getCallback() != null)) {
/*      */         try {
/* 1256 */           info.getCallback().postModify(context, name, entry);
/*      */         }
/*      */         catch (Exception e) {
/* 1259 */           ZimbraLog.account.warn("postModify caught exception: " + e.getMessage(), e);
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   public AttributeInfo getAttributeInfo(String name)
/*      */   {
/* 1268 */     if (name == null) {
/* 1269 */       return null;
/*      */     }
/* 1271 */     return (AttributeInfo)this.mAttrs.get(name.toLowerCase());
/*      */   }
/*      */   
/*      */   public static void loadLdapSchemaExtensionAttrs(LdapProv prov) {
/* 1275 */     synchronized (AttributeManager.class) {
/*      */       try {
/* 1277 */         AttributeManager theInstance = getInstance();
/* 1278 */         theInstance.getLdapSchemaExtensionAttrs(prov);
/* 1279 */         theInstance.computeClassToAllAttrsMap();
/*      */       } catch (ServiceException e) {
/* 1281 */         ZimbraLog.account.warn("unable to load LDAP schema extensions", e);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   private void getLdapSchemaExtensionAttrs(LdapProv prov) throws ServiceException {
/* 1287 */     if (this.mLdapSchemaExtensionInited) {
/* 1288 */       return;
/*      */     }
/* 1290 */     this.mLdapSchemaExtensionInited = true;
/*      */     
/* 1292 */     getExtraObjectClassAttrs(prov, AttributeClass.account, "zimbraAccountExtraObjectClass");
/* 1293 */     getExtraObjectClassAttrs(prov, AttributeClass.calendarResource, "zimbraCalendarResourceExtraObjectClass");
/* 1294 */     getExtraObjectClassAttrs(prov, AttributeClass.cos, "zimbraCosExtraObjectClass");
/* 1295 */     getExtraObjectClassAttrs(prov, AttributeClass.domain, "zimbraDomainExtraObjectClass");
/* 1296 */     getExtraObjectClassAttrs(prov, AttributeClass.server, "zimbraServerExtraObjectClass");
/*      */   }
/*      */   
/*      */   private void getExtraObjectClassAttrs(LdapProv prov, AttributeClass attrClass, String extraObjectClassAttr) throws ServiceException
/*      */   {
/* 1301 */     Config config = prov.getConfig();
/*      */     
/* 1303 */     String[] extraObjectClasses = config.getMultiAttr(extraObjectClassAttr);
/*      */     
/* 1305 */     if (extraObjectClasses.length > 0) {
/* 1306 */       Set<String> attrsInOCs = (Set)this.mClassToAttrsMap.get(AttributeClass.account);
/* 1307 */       prov.getAttrsInOCs(extraObjectClasses, attrsInOCs);
/*      */     }
/*      */   }
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/account/AttributeManager.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */